﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using TMTemplate;
using System.Windows.Navigation;

namespace TMLibrary
{
    public class PageTransitionBehavior : Behavior<UserControl>
    {
        bool isStartPagePresent;
        public bool isAnimating = false;
        public bool isFromControl = false;  
        public event EventHandler<NavigatedEventArgs> pNavigated;
        [Category("Common Properties"), Description("Gets or sets the name of navigation frame"), CustomPropertyValueEditor(CustomPropertyValueEditor.Element)]
        public string TargetFrame
        {
            get;
            set;
        }
        [Category("Common Properties"), Description("Sets a delay before navigating to a page in milliseconds")]
        public int TimeOut
        {
            get;
            set;
        }
        [Category("Common Properties"), Description("Gets or sets the name of the state to change to when opening a page"), CustomPropertyValueEditor(CustomPropertyValueEditor.StateName)]
        public string OpeningPageState
        {
            get;
            set;
        }
        [Category("Common Properties"), Description("Gets or sets the name of the state to change to when closing a page"),  CustomPropertyValueEditor(CustomPropertyValueEditor.StateName)]
        public string ClosingPageState
        {
            get;
            set;
        }
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
        }
        void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
            (AssociatedObject.FindName(TargetFrame) as Frame).Navigating += new System.Windows.Navigation.NavigatingCancelEventHandler(contentFrame_Navigating);
            (AssociatedObject.FindName(TargetFrame) as Frame).Navigated += new System.Windows.Navigation.NavigatedEventHandler(contentFrame_Navigated);
            (AssociatedObject.FindName(TargetFrame) as Frame).NavigationFailed += new System.Windows.Navigation.NavigationFailedEventHandler(TMPageTransitionBehavior_NavigationFailed);
            if ((AssociatedObject.FindName(TargetFrame) as Frame).Source != null)
            {
                isStartPagePresent = false;
            }
            else isStartPagePresent = true;
        }

        void TMPageTransitionBehavior_NavigationFailed(object sender, System.Windows.Navigation.NavigationFailedEventArgs e)
        {
           e.Handled = true;
			//
			Uri tm;
			if (e.Uri.ToString() == "")
				tm = new Uri(((App.Current.RootVisual as MainPage).pageTransition.contentFrame.UriMapper as UriMapper).UriMappings[0].Uri.ToString(), UriKind.RelativeOrAbsolute);
			else
				tm = new Uri("NotFound", UriKind.RelativeOrAbsolute);
			//
            //Uri tm = new Uri("NotFound",UriKind.RelativeOrAbsolute);
            (AssociatedObject.FindName(TargetFrame) as Frame).Navigate(tm);
            pNavigated.Invoke(this, new NavigatedEventArgs(tm));
        }
        void contentFrame_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            isFromControl = false;
        }
        void contentFrame_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            if (!isFromControl)
            {
                e.Cancel = true;
                isFromControl = true;
                NavigateTo(e.Uri);
                pNavigated.Invoke(this, new NavigatedEventArgs(e.Uri));
            }
            else
            {
                VisualStateManager.GoToState(AssociatedObject, OpeningPageState, true);
                UIHelper.SetTimeout(TimeOut, delegate()
                {
                    isAnimating = false;
                });
                isStartPagePresent = false;
            }
        }
        public void NavigateTo(Uri link)
        {
            if (!isAnimating)
            {
                isAnimating = true;
                if (!isStartPagePresent)
                {
                    VisualStateManager.GoToState(AssociatedObject, ClosingPageState, true);
                    UIHelper.SetTimeout(TimeOut, delegate()
                    {
                        (AssociatedObject.FindName(TargetFrame) as Frame).Navigate(link);
                    });
                }
                else
                {
                    (AssociatedObject.FindName(TargetFrame) as Frame).Navigate(link);
                }
                pNavigated.Invoke(AssociatedObject, new NavigatedEventArgs(link));
            }
        }
        public class NavigatedEventArgs : EventArgs
        {
            public Uri link;
            public NavigatedEventArgs(Uri e)
            {
                link = e;
            }
        }
    }
}